// Copyright 2019 Fuzhou Rockchip Electronics Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "aac_server_media_subsession.hh"
#include "MPEG4GenericRTPSink.hh"

#include "utils.h"

namespace easymedia {
static unsigned const samplingFrequencyTable[16] = {
    96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
    16000, 12000, 11025, 8000,  7350,  0,     0,     0};

AACServerMediaSubsession *AACServerMediaSubsession::createNew(
    UsageEnvironment &env, Live555MediaInput &wisInput,
    unsigned samplingFrequency, unsigned numChannels, unsigned char profile) {
  return new AACServerMediaSubsession(env, wisInput, samplingFrequency,
                                      numChannels, profile);
}

AACServerMediaSubsession::AACServerMediaSubsession(
    UsageEnvironment &env, Live555MediaInput &mediaInput,
    unsigned samplingFrequency, unsigned numChannels, unsigned char profile)
    : OnDemandServerMediaSubsession(env, True /*reuse the first source*/),
      fMediaInput(mediaInput), fSamplingFrequency(samplingFrequency),
      fNumChannels(numChannels) {
  unsigned char audioSpecificConfig[2];
  unsigned char const audioObjectType = profile + 1;
  unsigned char samplingFrequencyIndex = 0;
  for (unsigned char i = 0; i < 16; i++) {
    if (samplingFrequencyTable[i] == fSamplingFrequency) {
      samplingFrequencyIndex = i;
      break;
    }
  }
  audioSpecificConfig[0] =
      (audioObjectType << 3) | (samplingFrequencyIndex >> 1);
  // audioSpecificConfig[1] = (samplingFrequencyIndex<<7) |
  // (channelConfiguration<<3);
  audioSpecificConfig[1] = (samplingFrequencyIndex << 7) | (fNumChannels << 3);
  sprintf(fConfigStr, "%02X%02x", audioSpecificConfig[0],
          audioSpecificConfig[1]);
}

AACServerMediaSubsession::~AACServerMediaSubsession() { LOG_FILE_FUNC_LINE(); }

FramedSource *
AACServerMediaSubsession::createNewStreamSource(unsigned /*clientSessionId*/,
                                                unsigned &estBitrate) {
  LOG_FILE_FUNC_LINE();
  estBitrate = 96; // kbps, estimate
  return fMediaInput.audioSource();
}

RTPSink *AACServerMediaSubsession::createNewRTPSink(
    Groupsock *rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic,
    FramedSource *inputSource) {
  if (!inputSource) {
    LOG("inputSource is not ready, can not create new rtp sink\n");
    return NULL;
  }

  // ADTSAudioFileSource* adtsSource = (ADTSAudioFileSource*)inputSource;
  return MPEG4GenericRTPSink::createNew(
      envir(), rtpGroupsock, rtpPayloadTypeIfDynamic, fSamplingFrequency,
      "audio", "AAC-hbr", fConfigStr, fNumChannels);
}

// std::mutex AACServerMediaSubsession::kMutex;
void AACServerMediaSubsession::startStream(
    unsigned clientSessionId, void *streamToken, TaskFunc *rtcpRRHandler,
    void *rtcpRRHandlerClientData, unsigned short &rtpSeqNum,
    unsigned &rtpTimestamp,
    ServerRequestAlternativeByteHandler *serverRequestAlternativeByteHandler,
    void *serverRequestAlternativeByteHandlerClientData) {
  OnDemandServerMediaSubsession::startStream(
      clientSessionId, streamToken, rtcpRRHandler, rtcpRRHandlerClientData,
      rtpSeqNum, rtpTimestamp, serverRequestAlternativeByteHandler,
      serverRequestAlternativeByteHandlerClientData);
  // kMutex.lock();
  if (kSessionIdList.empty())
    fMediaInput.Start(envir());
  if (fMediaInput.GetStartAudioStreamCallback() != NULL) {
    fMediaInput.GetStartAudioStreamCallback()();
  }
  LOG("%s:%s:%p - clientSessionId: 0x%08x\n", __FILE__, __func__, this, clientSessionId);
  kSessionIdList.push_back(clientSessionId);
  // kMutex.unlock();
}
void AACServerMediaSubsession::deleteStream(unsigned clientSessionId,
                                            void *&streamToken) {
  // kMutex.lock();
  LOG("%s - clientSessionId: 0x%08x\n", __func__, clientSessionId);
  kSessionIdList.remove(clientSessionId);
  if (kSessionIdList.empty())
    fMediaInput.Stop(envir());
  // kMutex.unlock();
  OnDemandServerMediaSubsession::deleteStream(clientSessionId, streamToken);
}

} // namespace easymedia
